package dtm

import (
	"context"
	"fmt"
	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
	"gitee.com/xuyiping_admin/pkg/xerr"
	"github.com/goccy/go-json"
	"go.uber.org/zap"
	"kpt-dtm/model"
	"kpt-dtm/model/dtm"
	"kpt-dtm/model/yyn"
	"kpt-dtm/pkg"
	"reflect"
	"runtime"
	"strings"
	"time"
)

const (
	SurplusMethod       = "uploadoverplusdata"
	SpreadMethod        = "uploaddiliverdata"
	FormulationMethod   = "getfeedtempletinfo"
	MixMethod           = "uploadadddata"
	DryMatterMethod     = "uploaddrymatterdata"
	AccuracyMethod      = "uploadrate"
	PlanWightMethod     = "uploadweight"
	PlanCarNumberMethod = "uploadcarnumber"
)

var (
	FunctionStatuses = make(map[string]string)
	DropShiftList    = []rune{'早', '中', '晚', '夜'}
)

func (s *StoreEntry) DataHandle() error {
	startTime := time.Now()
	zaplog.Info("DataInit-01", zap.Any("startTime", startTime.Format(pkg.Layout)))
	
	// 设置超时控制，避免任务执行时间过长
	timeout := 30 * time.Minute // 30分钟超时
	done := make(chan error, 1)
	
	go func() {
		done <- s.executeDataInit()
	}()
	
	select {
	case err := <-done:
		duration := time.Since(startTime)
		zaplog.Info("DataInit-完成", 
			zap.Duration("duration", duration),
			zap.Error(err))
		return err
	case <-time.After(timeout):
		duration := time.Since(startTime)
		zaplog.Error("DataInit-超时", 
			zap.Duration("duration", duration),
			zap.Duration("timeout", timeout))
		return fmt.Errorf("DataInit执行超时: %v", timeout)
	}
}

func (s *StoreEntry) executeDataInit() error {
	appPastureList := make([]*model.AppPasture, 0)
	if err := s.DB.Table(new(model.AppPasture).TableName()).
		Where("is_show = ?", model.IsShowOK).
		Find(&appPastureList).Error; err != nil {
		return err
	}
	zaplog.Info("DataInit-02", zap.Any("appPastureList", appPastureList))
	if len(appPastureList) <= 0 {
		return nil
	}

	dayExecFuncList := s.GetLoopList()
	zaplog.Info("DataInit-03", zap.Any("dayExecFuncList", dayExecFuncList))
	for _, dayExecFunc := range dayExecFuncList {
		FunctionStatuses[dayExecFunc.Name] = time.Unix(dayExecFunc.CreatedAt, 0).Format(pkg.LayoutYear)
	}
	zaplog.Info("DataInit-04", zap.Any("FunctionStatuses", FunctionStatuses))
	
	for _, app := range appPastureList {
		zaplog.Info("DataInit-05", zap.Any("app", app))
		if app.SoftwareVersion == model.SoftwareVersionHigh {
			if err := s.NewAppPastureExecute(app); err != nil {
				zaplog.Error("DataInit", zap.Any("NewAppPastureExecute", err), zap.Any("app", app))
			}
		} else if app.SoftwareVersion == model.SoftwareVersionLow {
			if err := s.OldAppPastureExecute(app); err != nil {
				zaplog.Error("DataInit", zap.Any("OldAppPastureExecute", err), zap.Any("app", app))
			}
		}
	}

	return nil
}

func (s *StoreEntry) NewAppPastureExecute(app *model.AppPasture) error {
	ctx := context.Background()
	var err error

	if _, err = s.CompanyToken(ctx, app.Id); err != nil {
		zaplog.Error("DataInit", zap.Any("app", app), zap.Any("CompanyToken", err))
		return xerr.WithStack(err)
	}

	yConfig, err := s.GetYConfig(app.Id)
	if err != nil {
		zaplog.Error("DataInit", zap.Any("GetYConfig", err), zap.Any("app", app))
		return xerr.WithStack(err)
	}

	yMqtt, err := s.GetYMqtt(app.Id)
	if err != nil {
		zaplog.Error("DataInit", zap.Any("GetYMqtt", err), zap.Any("app", app))
	}

	// YynHouseInfoToDtmPen 更新栏舍信息
	if err = s.YynHouseInfoToDtmPen(ctx, app.Id, yConfig); err != nil {
		zaplog.Error("DataInit", zap.Any("app", app), zap.Any("YynHouseInfoToDtmPen", err))
	}

	funcList := s.NewExecuteFunctions(ctx)
	nowTime := time.Now().Format(pkg.LayoutYear)
	zaplog.Info("DataInit", zap.Any("FunctionStatuses", FunctionStatuses), zap.Any("app", app), zap.Any("nowTime", nowTime))

	for _, f := range funcList {
		funcName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() // 获取函数名，注意这种方法并不推荐，因为它使用了反射和运行时包，可能不是最可靠或最高效的方法
		funcName = funcName[strings.LastIndex(funcName, ".")+1:]           // 提取函数名部分
		funcName = funcName[:strings.LastIndex(funcName, "-")]             // 提取函数名部分
		if FunctionStatuses[funcName] == nowTime {
			zaplog.Info("DataInit", zap.Any("app", app), zap.String("跳过已执行的函数", funcName))
			continue
		}

		zaplog.Info("DataInit",
			zap.String("正在执行的函数", funcName),
			zap.Any("app", app),
			zap.Any("yConfig", yConfig),
			zap.Any("yMqtt", yMqtt),
		)
		if err = f(ctx, app.Id, yConfig, yMqtt); err != nil {
			zaplog.Error("DataInit", zap.Any("app", app), zap.String("functionName", funcName), zap.Any("err", err))
			s.CreateErrorLog(app.Id, funcName, err.Error())
			continue
		}
		// 这两步暂时不考虑一致性
		FunctionStatuses[funcName] = nowTime
		zaplog.Info("DataInit", zap.String("执行结束的函数", funcName))
		if err = s.CreateLoop(app.Id, funcName); err != nil {
			zaplog.Error("DataInit", zap.Any("app", app), zap.Any("CreateLoop", err))
		}
	}
	return nil
}

func (s *StoreEntry) NewExecuteFunctions(ctx context.Context) []func(context.Context, int64, *model.YConfig, *model.YMqtt) error {
	functions := []func(context.Context, int64, *model.YConfig, *model.YMqtt) error{
		s.FormulationData,
		s.DryMatterData,
		s.MixingData,
		s.SpreadingData,
		s.AccuracyRatio,
		s.TrainNumberAndCompletedWeight,
	}
	return functions
}

// FormulationData 配方数据
func (s *StoreEntry) FormulationData(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip                  = 0
		formulationValuesList = make([]*dtm.FormulationValues, 0)
		res                   interface{}
		inter                 interface{}
		err                   error
	)

	res, err = s.FormulationByDataList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.FormulationResponse)
	if len(dataList.Value) > 0 {
		formulationValuesList = append(formulationValuesList, dataList.Value...)
		skip += len(dataList.Value)
	}

	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}

				dataList = inter.(*dtm.FormulationResponse)
				formulationValuesList = append(formulationValuesList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.FormulationByDataList); err != nil {
		return xerr.WithStack(err)
	}

	resultData := make([]*yyn.FormulationData, 0)
	for _, recipeList := range formulationValuesList {
		for _, ingred := range recipeList.RecipeIngredient {
			// 判断配方数据是否存在
			if s.IsCheckFormulation(pastureId, fmt.Sprintf("%d", recipeList.RecipeId), fmt.Sprintf("%d", ingred.IngredientId)) {
				continue
			}
			resultData = append(resultData, &yyn.FormulationData{
				RecipeId:   fmt.Sprintf("%d", recipeList.RecipeId),
				RecipeName: recipeList.Name,
				IngId:      fmt.Sprintf("%d", ingred.IngredientId),
				IngName:    ingred.IngredientName,
				DmQty:      fmt.Sprintf("%.2f", ingred.DmPerc),
				AfQty:      fmt.Sprintf("%.2f", ingred.WeightCow),
				RecipeCost: fmt.Sprintf("%.2f", ingred.IngredientCost),
				MixNo:      fmt.Sprintf("%d", ingred.Position),
				IsPreMix:   recipeList.Premix,
				DmPercTot:  ingred.DmPerc,
			})
		}
	}

	if len(resultData) <= 0 {
		return nil
	}
	// 推送配方数据
	if err = s.FormulationDataPush(pastureId, yConfig, yMqtt, resultData); err != nil {
		return xerr.WithStack(err)
	}

	newFormulationList := model.NewFormulationList(pastureId, resultData)
	if err = s.CreateFormulation(newFormulationList); err != nil {
		return xerr.WithStack(err)
	}
	return nil
}

// DryMatterData 干物质数据
func (s *StoreEntry) DryMatterData(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip               = 0
		dryMatterValueList = make([]*dtm.BatchHistValue, 0)
		res                interface{}
		inter              interface{}
		err                error
		formulation        *model.Formulation
	)
	res, err = s.BatchHistByDayList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.BatchHistResponse)
	if len(dataList.Value) > 0 {
		dryMatterValueList = append(dryMatterValueList, dataList.Value...)
		skip += len(dataList.Value)
	}

	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}
				dataList = inter.(*dtm.BatchHistResponse)
				dryMatterValueList = append(dryMatterValueList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.BatchHistByDayList); err != nil {
		return xerr.WithStack(err)
	}

	resultData := make([]*yyn.DryMatter, 0)
	for _, batch := range dryMatterValueList {
		if s.IsCheckDryMatter(pastureId, batch.EnableLoadId) {
			continue
		}

		formulation, err = s.GetFormulation(batch.RecipeId)
		if err != nil {
			zaplog.Error("DryMatterInfo", zap.Any("formulation-Err", err))
		}
		dryMatter := ""
		if formulation.DmPercTot > 0 {
			dryMatter = fmt.Sprintf("%.2f", float64(formulation.DmPercTot)/100)
		}

		t, _ := pkg.UTCTimeToLoadTime(batch.LoadDate)
		startTime, _ := pkg.UTCTimeToLoadTime(batch.LoadStartTime)
		endTime, _ := pkg.UTCTimeToLoadTime(batch.LoadEndTime)

		resultData = append(resultData, &yyn.DryMatter{
			QualityDate: t.Format(pkg.Layout),
			RecipeId:    fmt.Sprintf("%d", batch.RecipeId),
			RecipeName:  batch.RecipeName,
			Drymatter:   dryMatter,
			StartTime:   startTime.Format(pkg.Layout),
			EndTime:     endTime.Format(pkg.Layout),
			ElabLoadId:  int64(batch.EnableLoadId),
		})
	}

	if len(resultData) <= 0 {
		return nil
	}

	// 干物质数据推送
	if err = s.DryMatterDataPush(pastureId, yConfig, yMqtt, resultData); err != nil {
		return xerr.WithStack(err)
	}

	newDryMatterList := model.NewDryMatterList(pastureId, resultData)
	if err = s.CreatedDryMatter(newDryMatterList); err != nil {
		return xerr.WithStack(err)
	}
	return nil
}

// MixingData 搅拌数据
func (s *StoreEntry) MixingData(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip            = 0
		mixingValueList = make([]*dtm.BatchHistValue, 0)
		res             interface{}
		inter           interface{}
		err             error
	)
	res, err = s.BatchHistByDayList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.BatchHistResponse)
	if len(dataList.Value) > 0 {
		mixingValueList = append(mixingValueList, dataList.Value...)
		skip += len(dataList.Value)
	}

	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}
				dataList = inter.(*dtm.BatchHistResponse)
				mixingValueList = append(mixingValueList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.BatchHistByDayList); err != nil {
		return xerr.WithStack(err)
	}

	resultData := make([]*yyn.MixData, 0)
	for _, v := range mixingValueList {
		// 判断剩料数据是否存在
		if s.IsCheckMixing(pastureId, v.LoadEndTime, v.RecipeId, v.EnableLoadId) {
			continue
		}

		batchHistDetail, err := s.BatchHistDetail(ctx, v.EnableLoadId, pastureId)
		if err != nil {
			zaplog.Error("MixingData", zap.Any("BatchHistDetail-Err", err))
			continue
		}

		if len(batchHistDetail.Value) <= 0 {
			zaplog.Error("MixingData", zap.Any("BatchHistDetail-Value", batchHistDetail))
			continue
		}

		t, _ := pkg.UTCTimeToLoadTime(v.LoadDate)
		st, _ := pkg.UTCTimeToLoadTime(v.LoadStartTime)
		et, _ := pkg.UTCTimeToLoadTime(v.LoadEndTime)

		ingType := 11
		if !v.Premix {
			ingType = 12
		}

		foundChar := pkg.ContainsRune(v.BatchName, DropShiftList)
		dropShift := "3"
		if foundChar != rune(0) {
			switch string(foundChar) {
			case "早":
				dropShift = "1"
			case "中":
				dropShift = "2"
			case "晚":
				dropShift = "3"
			default:
				dropShift = "3"
			}
		}

		for _, bath := range batchHistDetail.Value {
			if bath.ElabLoadId != v.EnableLoadId {
				continue
			}
			for j, ing := range bath.Ingredients {
				FormulationData, _ := s.GetFormulationByIng(v.RecipeId, ing.IngredientId)
				resultData = append(resultData, &yyn.MixData{
					LoadDate:       t.Format(pkg.LayoutYear),
					TmrNo:          fmt.Sprintf("%d", j+1),
					LoadShift:      dropShift,
					RecipeId:       fmt.Sprintf("%d", v.RecipeId),
					RecipeName:     v.RecipeName,
					IngId:          fmt.Sprintf("%d", ing.IngredientId),
					IngName:        ing.IngredientName,
					IngType:        fmt.Sprintf("%d", ingType),
					DmPct:          fmt.Sprintf("%.2f", float64(FormulationData.DmPercTot)/100),
					MixNo:          fmt.Sprintf("%d", j+1),
					AllowableError: fmt.Sprintf("%.2f", v.LoadPercError),
					ExpWeight:      fmt.Sprintf("%.2f", ing.TargetWeight),
					ActualWeight:   fmt.Sprintf("%.2f", ing.Loaded),
					StartTime:      st.Format(pkg.Layout),
					EndTime:        et.Format(pkg.Layout),
					TmrName:        v.MachineName,
					ElabLoadId:     v.EnableLoadId,
				})
			}
		}
	}
	if len(resultData) <= 0 {
		return nil
	}
	// 搅拌数据推送
	if err = s.MixingDataPush(pastureId, yConfig, yMqtt, resultData); err != nil {
		return xerr.WithStack(err)
	}

	newMixDataList := model.NewMixDataList(pastureId, resultData)
	if err = s.CreateMixing(newMixDataList); err != nil {
		return xerr.WithStack(err)
	}
	return nil
}

// SpreadingData 撒料数据
func (s *StoreEntry) SpreadingData(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip            = 0
		mixingValueList = make([]*dtm.BatchHistValue, 0)
		res             interface{}
		inter           interface{}
		err             error
	)
	res, err = s.BatchHistByDayList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.BatchHistResponse)
	if len(dataList.Value) > 0 {
		mixingValueList = append(mixingValueList, dataList.Value...)
		skip += len(dataList.Value)
	}
	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}
				dataList = inter.(*dtm.BatchHistResponse)
				mixingValueList = append(mixingValueList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.BatchHistByDayList); err != nil {
		return xerr.WithStack(err)
	}
	resultData := make([]*yyn.UploadDiliverData, 0)
	for i, v := range mixingValueList {
		// 判断剩料数据是否存在
		if s.IsCheckSpread(pastureId, v.EnableLoadId) {
			continue
		}
		// 转换时间格式
		t, _ := pkg.UTCTimeToLoadTime(v.LoadDate)
		st, _ := pkg.UTCTimeToLoadTime(v.LoadStartTime)
		et, _ := pkg.UTCTimeToLoadTime(v.LoadEndTime)

		foundChar := pkg.ContainsRune(v.MachineName, DropShiftList)
		dropShift := ""
		if foundChar != rune(0) {
			dropShift = fmt.Sprintf("%s班", string(foundChar))
		}

		bathList, err := s.DtmBatch(ctx, 0, fmt.Sprintf("batchId eq %d", v.BatchId), pastureId)
		zaplog.Info("SpreadMethod003", zap.Any("bathList", bathList), zap.Any("err", err))
		if err != nil {
			zaplog.Error("SpreadingData", zap.Any("DtmBatch", err))
			continue
		}
		if len(bathList.Value) <= 0 {
			continue
		}
		for _, bath := range bathList.Value {
			if len(bath.BatchPenRation) <= 0 {
				continue
			}
			for _, b := range bath.BatchPenRation {
				resultData = append(resultData, &yyn.UploadDiliverData{
					DropDate:     t.Format(pkg.LayoutYear),
					TmrNo:        fmt.Sprintf("%d", i),
					DropShift:    dropShift,
					PenId:        fmt.Sprintf("%d", b.PenId),
					PenName:      b.PenName,
					CowCount:     fmt.Sprintf("%d", b.NCows),
					FeedingNo:    fmt.Sprintf("%d", b.Position),
					ExpWeight:    fmt.Sprintf("%.2f", v.TargetWeightWithCorr),
					ActualWeight: fmt.Sprintf("%.2f", v.Loaded),
					StartTime:    st.Format(pkg.Layout),
					EndTime:      et.Format(pkg.Layout),
					TmrName:      v.MachineName,
					ElabLoadId:   int64(v.EnableLoadId),
				})
			}
		}
	}

	zaplog.Info("SpreadMethod004", zap.Any("resultData", resultData))
	if len(resultData) <= 0 {
		return nil
	}

	// 撒料数据推送
	if err = s.SpreadDataPush(pastureId, yConfig, yMqtt, resultData); err != nil {
		return xerr.WithStack(err)
	}

	newSpreadList := model.NewSpreadList(pastureId, resultData)
	if err = s.CreateSpread(newSpreadList); err != nil {
		return xerr.WithStack(err)
	}
	return nil
}

// SurplusData 剩料数据
func (s *StoreEntry) SurplusData(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip             = 0
		surplusValueList = make([]*dtm.RefusedByDayValues, 0)
		res              interface{}
		inter            interface{}
		err              error
	)
	res, err = s.RefusedByDayList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.RefusedByDayResponse)
	if len(dataList.Value) > 0 {
		surplusValueList = append(surplusValueList, dataList.Value...)
		skip += len(dataList.Value)
	}

	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}
				dataList = inter.(*dtm.RefusedByDayResponse)
				surplusValueList = append(surplusValueList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.RefusedByDayList); err != nil {
		return xerr.WithStack(err)
	}

	resultData := make([]*yyn.MqttOverPlusData, 0)
	for _, v := range surplusValueList {
		// 判断剩料数据是否存在
		if s.IsCheckSurplus(pastureId, v.PenId, v.RefusedDate) {
			continue
		}
		// 转换时间格式
		t, _ := pkg.UTCTimeToLoadTime(v.RefusedDate)
		resultData = append(resultData, &yyn.MqttOverPlusData{
			OverPlusDate: t.Format(pkg.LayoutYear),
			PenId:        fmt.Sprintf("%d", v.PenId),
			PenName:      v.PenName,
			ActualWeight: fmt.Sprintf("%.2f", v.TotalRefusedQty),
			StartTime:    v.RefusedDate,
			EndTime:      v.RefusedDate,
		})
	}
	if len(resultData) <= 0 {
		return nil
	}
	body := yyn.MqttMessage{
		ReqMethod: yMqtt.ReqMethod,
		RegCode:   yMqtt.RegCode,
		Command:   yMqtt.Command,
		ModelType: yMqtt.ModelType,
		ApiId:     yMqtt.ApiId,
		Param: &yyn.Param{
			FarmId:     yConfig.FarmNumber,
			Method:     SurplusMethod,
			Code:       "1",
			ErrMessage: "",
			RowCount:   fmt.Sprintf("%d", len(resultData)),
			ResultData: resultData,
		},
	}
	b, _ := json.Marshal(body)
	if token := s.MqttManager.Publish(fmt.Sprintf("%d", pastureId), string(b)); token.Wait() && token.Error() != nil {
		return xerr.WithStack(token.Error())
	}
	surplusList := model.NewSurplusList(pastureId, resultData)
	if err = s.CreateSurplus(surplusList); err != nil {
		return xerr.WithStack(err)
	}
	return nil
}

// AccuracyRatio 准确率
func (s *StoreEntry) AccuracyRatio(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		skip              = 0
		accuracyValueList = make([]*dtm.BatchHistValue, 0)
		res               interface{}
		inter             interface{}
		err               error
	)
	res, err = s.BatchHistByDayList(ctx, skip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	dataList := res.(*dtm.BatchHistResponse)
	if len(dataList.Value) > 0 {
		accuracyValueList = append(accuracyValueList, dataList.Value...)
		skip += len(dataList.Value)
	}

	paginate := func(fun PaginateHandleFunc) error {
		if dataList.OdataCount > skip {
			for {
				inter, err = fun(ctx, skip, pastureId)
				if err != nil {
					return xerr.WithStack(err)
				}
				dataList = inter.(*dtm.BatchHistResponse)
				accuracyValueList = append(accuracyValueList, dataList.Value...)
				skip += len(dataList.Value)
				if skip >= dataList.OdataCount {
					break
				}
			}
		}
		return nil
	}

	if err = paginate(s.BatchHistByDayList); err != nil {
		return xerr.WithStack(err)
	}

	resultData := make([]*yyn.AccuracyData, 0)
	for _, v := range accuracyValueList {
		// 转换时间格式
		t, _ := pkg.UTCTimeToLoadTime(v.LoadDate)
		startTime, _ := pkg.UTCTimeToLoadTime(v.LoadStartTime)
		endTime, _ := pkg.UTCTimeToLoadTime(v.LoadEndTime)
		resultData = append(resultData, &yyn.AccuracyData{
			RateDate:  t.Format(pkg.LayoutYear),
			Name:      v.RecipeName,
			Rate:      fmt.Sprintf("%.2f", v.ErrPercLoad),
			StartTime: startTime.Format(pkg.Layout),
			EndTime:   endTime.Format(pkg.Layout),
		})
	}
	if len(resultData) <= 0 {
		return nil
	}
	body := yyn.MqttMessage{
		ReqMethod: yMqtt.ReqMethod,
		RegCode:   yMqtt.RegCode,
		Command:   yMqtt.Command,
		ModelType: yMqtt.ModelType,
		ApiId:     yMqtt.ApiId,
		Param: &yyn.Param{
			FarmId:     yConfig.FarmNumber,
			Method:     AccuracyMethod,
			Code:       "1",
			ErrMessage: "",
			RowCount:   fmt.Sprintf("%d", len(resultData)),
			ResultData: resultData,
		},
	}
	b, _ := json.Marshal(body)
	if token := s.MqttManager.Publish(fmt.Sprintf("%d", pastureId), string(b)); token.Wait() && token.Error() != nil {
		return xerr.WithStack(token.Error())
	}
	return nil
}

// TrainNumberAndCompletedWeight 完成车次和车次重量
func (s *StoreEntry) TrainNumberAndCompletedWeight(ctx context.Context, pastureId int64, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		planSkip, completeSkip = 0, 0
	)

	bathList, err := s.DtmBatch(ctx, planSkip, "", pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}

	bathHistList, err := s.BatchHistByDayList(ctx, completeSkip, pastureId)
	if err != nil {
		return xerr.WithStack(err)
	}
	dataList := bathHistList.(*dtm.BatchHistResponse)

	if err = s.TrainNumber(pastureId, bathList, dataList, yConfig, yMqtt); err != nil {
		return xerr.WithStack(err)
	}

	if err = s.CompletedWeight(pastureId, bathList, dataList, yConfig, yMqtt); err != nil {
		return xerr.WithStack(err)
	}

	return nil
}

func (s *StoreEntry) TrainNumber(pastureId int64, bathList *dtm.BatchResponse, bathHistList *dtm.BatchHistResponse, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		TodayAllPanTrainNumber, TodayAllCompleteTrainNumber = 0, 0
		numberStartTime, numberEndTime                      = "", ""
	)

	TodayAllPanTrainNumber = bathList.OdataCount
	TodayAllCompleteTrainNumber = bathHistList.OdataCount

	if len(bathList.Value) > 0 {
		ns, _ := pkg.UTCTimeToLoadTime(bathList.Value[0].LastModify)
		numberStartTime = ns.Format(pkg.Layout)
		numberEndTime = ns.Format(pkg.Layout)
	}

	body := yyn.MqttMessage{
		ReqMethod: yMqtt.ReqMethod,
		RegCode:   yMqtt.RegCode,
		Command:   yMqtt.Command,
		ModelType: yMqtt.ModelType,
		ApiId:     yMqtt.ApiId,
		Param: &yyn.Param{
			FarmId:     yConfig.FarmNumber,
			Method:     PlanCarNumberMethod,
			Code:       "1",
			ErrMessage: "",
			RowCount:   "1",
			ResultData: nil,
		},
	}

	planCarNumberList := make([]*yyn.PlanCarNumberData, 0)
	planCarNumberList = append(planCarNumberList, &yyn.PlanCarNumberData{
		CompleteCar: fmt.Sprintf("%d", TodayAllCompleteTrainNumber),
		CarDate:     time.Now().Format(pkg.LayoutYear),
		PlanCar:     fmt.Sprintf("%d", TodayAllPanTrainNumber),
		StartTime:   numberStartTime,
		EndTime:     numberEndTime,
	})

	body.Param.ResultData = planCarNumberList
	b, _ := json.Marshal(body)
	if token := s.MqttManager.Publish(fmt.Sprintf("%d", pastureId), string(b)); token.Wait() && token.Error() != nil {
		return xerr.WithStack(token.Error())
	}
	return nil
}

func (s *StoreEntry) CompletedWeight(pastureId int64, bathList *dtm.BatchResponse, bathHistList *dtm.BatchHistResponse, yConfig *model.YConfig, yMqtt *model.YMqtt) error {
	var (
		TodayAllPlanWight, TodayAllCompleteWight = 0.0, 0.0
		weightStartTime, weightEndTime           = "", ""
	)

	for _, v := range bathList.Value {
		TodayAllPlanWight += v.TotalWeight
	}

	for _, v := range bathHistList.Value {
		TodayAllCompleteWight += v.Loaded
	}

	if len(bathHistList.Value) > 0 {
		wt, _ := pkg.UTCTimeToLoadTime(bathHistList.Value[0].LoadStartTime)
		weightStartTime = wt.Format(pkg.Layout)
		et, _ := pkg.UTCTimeToLoadTime(bathHistList.Value[len(bathHistList.Value)-1].LoadEndTime)
		weightEndTime = et.Format(pkg.Layout)
	}

	body := yyn.MqttMessage{
		ReqMethod: yMqtt.ReqMethod,
		RegCode:   yMqtt.RegCode,
		Command:   yMqtt.Command,
		ModelType: yMqtt.ModelType,
		ApiId:     yMqtt.ApiId,
		Param: &yyn.Param{
			FarmId:     yConfig.FarmNumber,
			Method:     PlanWightMethod,
			Code:       "1",
			ErrMessage: "",
			RowCount:   "1",
			ResultData: nil,
		},
	}

	planWeightDataList := make([]*yyn.PlanWeightData, 0)
	planWeightDataList = append(planWeightDataList, &yyn.PlanWeightData{
		CompleteWeight: fmt.Sprintf("%.2f", TodayAllCompleteWight),
		WeightDate:     time.Now().Format(pkg.LayoutYear),
		PlanWeight:     fmt.Sprintf("%.2f", TodayAllPlanWight),
		StartTime:      weightStartTime,
		EndTime:        weightEndTime,
	})

	body.Param.ResultData = planWeightDataList
	b, _ := json.Marshal(body)
	if token := s.MqttManager.Publish(fmt.Sprintf("%d", pastureId), string(b)); token.Wait() && token.Error() != nil {
		return xerr.WithStack(token.Error())
	}
	return nil
}
